package com.dabai.qrtools.ui

import android.Manifest
import android.annotation.SuppressLint
import android.content.Intent
import android.graphics.Rect
import android.graphics.RectF
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.util.Log
import android.util.Size
import android.view.ViewTreeObserver
import android.view.WindowManager
import android.widget.ImageView
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.camera.core.*
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.view.PreviewView
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.lifecycle.LifecycleOwner
import com.dabai.qrtools.qrcode.mlkit.ScanOverlay
import com.dabai.qrtools.R
import com.dabai.qrtools.qrcode.QRCodeUtils
import com.dabai.qrtools.qrcode.ScanUtils
import com.google.common.util.concurrent.ListenableFuture
import java.util.concurrent.Executors

import com.dabai.qrtools.qrcode.mlkit.QRCodeAnalyser
import com.dabai.qrtools.qrcode.mlkit.isPortraitMode
import com.dabai.qrtools.utils.DabaiUtils
import com.dabai.qrtools.utils.NotificationUtils
import com.google.zxing.decoding.CaptureActivityHandler
import java.io.IOException
import java.lang.RuntimeException


class QrCodeScannerActivity : AppCompatActivity() {

    private val TAG = "DBTAG"

    private lateinit var cameraProviderFuture : ListenableFuture<ProcessCameraProvider>

    private var listener : OverlayListener? = null

    private var camera : Camera? = null

    private var scaleX = 0f

    private var scaleY = 0f

    private lateinit var overlay : ScanOverlay
    private lateinit var previewView : PreviewView
    private lateinit var button1 : ImageView
    private lateinit var button2 : ImageView
    private lateinit var button3 : ImageView

    companion object{
        const val REQUEST_PERMISSION = 12345
    }


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_barcode_scanning)

        window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                                WindowManager.LayoutParams.FLAG_FULLSCREEN);// 隐藏状态栏

        ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA),
            REQUEST_PERMISSION
        )
        cameraProviderFuture = ProcessCameraProvider.getInstance(this)
        listener = OverlayListener()

        overlay = findViewById(R.id.overlay)
        previewView = findViewById(R.id.previewView)
        button1 = findViewById(R.id.iv_exit)

        button1.setOnClickListener {
            finish()
        }
        button2 = findViewById(R.id.iv_photo)

        button2.setOnClickListener {

            //打开手机中的相册
            val innerIntent =
                Intent(Intent.ACTION_GET_CONTENT) //"android.intent.action.GET_CONTENT"
            innerIntent.type = "image/*"
            startActivityForResult(innerIntent, 100)

        }

        button3 = findViewById(R.id.iv_flash)

        button3.setOnClickListener {


            isFlashOn = if (isFlashOn) {
                // 关闭闪光灯
                camera?.cameraControl?.enableTorch(false)
                button3.setImageResource(R.drawable.ic_outline_flash_off_24)
                false
            } else {
                // 开启闪光灯
                camera?.cameraControl?.enableTorch(true)
                button3.setImageResource(R.drawable.ic_outline_flash_on_24)
                true
            }

        }

        overlay.viewTreeObserver.addOnGlobalLayoutListener(listener)
        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
    }


    private var isFlashOn = false

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if(REQUEST_PERMISSION == requestCode){
            if (grantResults.asList().contains(-1)){
                Toast.makeText(this,"启动失败,未授予相机权限!",Toast.LENGTH_LONG).show()
                finish()
            }
        }
    }

    inner class OverlayListener : ViewTreeObserver.OnGlobalLayoutListener {
        @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
        override fun onGlobalLayout() {
            cameraProviderFuture.addListener({
                val cameraProvider = cameraProviderFuture.get()
                bindScan(cameraProvider, overlay.width, overlay.height)
            }, ContextCompat.getMainExecutor(this@QrCodeScannerActivity))
            overlay.viewTreeObserver.removeOnGlobalLayoutListener(listener)
        }
    }

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    @SuppressLint("UnsafeExperimentalUsageError")
    private fun bindScan(cameraProvider: ProcessCameraProvider,width : Int, height : Int){

        Log.i(TAG, "DBA二维码扫描库输出 : 屏幕尺寸: width:$width height:$height")

        val preview : Preview = Preview.Builder()
            .build()

        //绑定预览
        preview.setSurfaceProvider(previewView.surfaceProvider)

        //使用后置相机
        val cameraSelector : CameraSelector = CameraSelector.Builder()
            .requireLensFacing(CameraSelector.LENS_FACING_BACK)
            .build()

        //配置图片扫描
        val imageAnalysis = ImageAnalysis.Builder()
            .setTargetResolution(Size(width, height))
            .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
            .build()
        //绑定图片扫描解析
        imageAnalysis.setAnalyzer(Executors.newSingleThreadExecutor(),
            QRCodeAnalyser { barcode, imageWidth, imageHeight ->
                //解绑当前所有相机操作
                cameraProvider.unbindAll()

                //初始化缩放比例
                initScale(imageWidth, imageHeight)
                barcode.boundingBox?.let {//扫描二维码的外边框矩形
                    overlay.addRect(translateRect(it))
                    Log.i(
                        TAG,
                        "二维码坐标: left:${it.left} right:${it.right} top:${it.top} bottom:${it.bottom}"
                    )
                    QRCodeUtils.playSound(this)
                    QRCodeUtils.playVibration(this)
                }
                Handler().postDelayed({
                    //延迟1S后返回结果
                    val intent = Intent()
                    intent.putExtra("qrContent", barcode.rawValue)
                    setResult(RESULT_OK, intent)
                    finish()
                }, 400)
            })
        //将相机绑定到当前控件的生命周期
        camera = cameraProvider.bindToLifecycle(this as LifecycleOwner, cameraSelector, imageAnalysis, preview)
    }

    private fun translateX(x: Float): Float = x * scaleX
    private fun translateY(y: Float): Float = y * scaleY

    //将扫描的矩形换算为当前屏幕大小
    private fun translateRect(rect: Rect) = RectF(
        translateX(rect.left.toFloat()),
        translateY(rect.top.toFloat()),
        translateX(rect.right.toFloat()),
        translateY(rect.bottom.toFloat())
    )

    private fun initScale(imageWidth : Int, imageHeight : Int){
        if(isPortraitMode(this)){
            scaleY = overlay.height.toFloat() / imageWidth.toFloat()
            scaleX = overlay.width.toFloat() / imageHeight.toFloat()
        }else{
            scaleY = overlay.height.toFloat() / imageHeight.toFloat()
            scaleX = overlay.width.toFloat() / imageWidth.toFloat()
        }
    }


    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        if (resultCode == RESULT_OK) {
            when (requestCode) {
                100 -> {
                    val result = ScanUtils.scanningImage(this, data?.data)
                    if (result != null){
                        val intent = Intent()
                        intent.putExtra("qrContent", result.text)
                        setResult(RESULT_OK, intent)
                        finish()
                    }else{
                        DabaiUtils.showToast(this,"识别失败")
                    }
                }
            }
        }
        super.onActivityResult(requestCode, resultCode, data)
    }


}